//Copyright 2012 Trevin Liberty
//GNU GPL v3
//Author: Trevin Liberty
//
//GameWorld holds all game related information.
//This is where updating and drawing everything happens.

#ifndef GAME_WORLD_H
#define GAME_WORLD_H

#include <iostream>
#include <allegro5\allegro.h>
#include <list>

#include "Doohickeys\Pathing\Pathing Thread.h"
#include "Doohickeys\Entity.h"
#include "Doohickeys\Buildings\Barracks.h"
#include "Sprite\MovingSprite.h"
#include "camera.h"
#include "GUI.h"
#include "Cursor.h"


using std::list;

//See comment at top of file for a complete description
class GameWorld {
private:
	Map* map;

	AStar* aStar;
	PathingThread* pathThread;

	//SEE: Structs.h
	PlayerResources playerRes;

	//Lists for all Entities, Buildings(Doohickeys), and Sprites.
	//Used for updating
	list<Entity*> entities;
	list<Doohickey*> buildings;
	list<MovingSprite*> movingSprites;

	//List of Entities that are selected by the user.
	//Used to give move orders to specific Entities.
	list<Entity*>* selectedEnts;

	//Used like selectedEnts but for a single Building
	Doohickey* selectedBuilding;

	//Pointer to THE barracks.
	//Used to create units. SEE: unitBuildQueue
	Barracks* barracks;

	//List of units that the player wants created.
	//Barracks takes units individually and allows them to be
	//	created after a certain amount of time.
	list<Entity*> unitBuildQueue;

	GUI* gui;
	Camera* camera;
	Cursor* cursor;

	int windowWidth;
	int windowHeight;

	imageArray* base;
	imageArray* fringe;

	ALLEGRO_DISPLAY* display;

	Point<float> lastLeftClick;
	Point<float> lastMiddleClick;

	void loadObjects();
	list<Entity*>::iterator removeEntity(list<Entity*>::iterator it);

public:
	//Constructor for GameWorld.
	//
	//	PARAMS:
	//Map* map: Pre loaded map/level of the game. SEE: Map_Loader.h, Structs.h
	//int windowWidth: The width, in pixels, of the display.
	//int windowHeight: the height, in pixels, of the display.
	//ALLEGRO_DISPLAY* display: A created Allegro display. SEE: Allegro_Misc.h
	GameWorld(Map* map, int windowWidth, int windowHeight, ALLEGRO_DISPLAY* display);

	//Initiates the GameWorld.
	//
	//ATTN: Must be called after creating a new GameWorld.
	//
	//	PARAMS:
	//imageArray &base. Pre loaded imageArray. SEE: Allegro_Misc.h, Structs.h
	//imageArray &fringe. SEE: imageArray &base.
	void initGameWorld(imageArray &base, imageArray &fringe) {this->base = &base; this->fringe = &fringe;}

	//Returns the game Camera. SEE: Camera.h
	Camera* getCamera() const {return camera;}

	//Returns true if the GameWorld has the entity, else false.
	//	PARAMS:
	//int id: The unique identification of a Doohickey. SEE: Doohcikey.h
	bool hasEntity(int id);

	//If GameWorld contains an Entity with the same id as the passed int, return Entity.
	//else return NULL.
	//	PARAMS:
	//int id: The unique identification of a Doohickey. SEE: Doohcikey.h
	Entity* getEntity(int id);

	//Adds the passed Entity to the GameWorld.
	//Returns true if completed successfully, else false.
	//	PARAMS:
	//Entity* e: A new Entity, with its position set. SEE: Entity.h
	bool addEntity(Entity* e);

	//Sets the goal of all Entities that are in the selectedEnts list.
	//If the goal is valid (within map bounds and on a walkable mapCell) the Entities
	//	can find paths to the goal, else return and do nothing.
	//	PARAMS:
	//Point<float> goal: ACTUAL SCREEN POSITION + (offset by camera). NOT mapArray Position (index). SEE: Point.h
	void setSelectedEntitiesGoal(Point<float> goal);

	//Returns true if the GameWorld has selected Entities.
	bool hasSelected() {return !selectedEnts->empty();}

	//Pushes all Entities within topLeft and bottomRight into selectedEnts list.
	//ATTN: corner1 and corner2 points must be ACTUAL SCREEN POSITION + (offset by camera). Not mapArray Position (Index)
	//ATTN: corner1 and corner2 do NOT have to be the topLeft and bottomRight corners of the rectangle.
	//	They only have to be opposite corners.
	//	PARAMS:
	//Point<int> corner1: A point representing a corner of a rectangle. Opposite of corner2. SEE: Point.h
	//Point<int> corner2: A point representing a corner of a rectangle. Opposite of corner1. SEE: Point.h
	void getDoohickeysWithin(Point<int> corner1, Point<int> corner2);

	//Removes all Entities from the selectedEnts list. Upon return, selectedEnts is empty.
	void deSelectEntites();

	//Resizes the window. Used to change between windowed and full screen, or change windowed sizes.
	//	PARAMS:
	//int width: The new width of the Screen.
	//int height: The new height of the Screen.
	void setWindowSize(int width, int height);

	//Call when the left mouse button is clicked DOWN.
	//For the time that this function was called and function: leftClickUp(...) is called,
	//	A rectangle is drawn to the screen symbolizing what the user will select. SEE: getDoohickeysWithin(...)
	//Also used to select unit building buttons. SEE: GUI.h
	void leftClickDown(Point<float> pos);

	//Call when the left mouse button is released UP.
	//Calls getDoohickeysWithin(...), using the position of the first mouseClick and the passed pos.
	void leftClickUp(Point<float> pos);

	//Call when the right mouse button is clicked DOWN.
	//Sets all Entities in selectedEnts list to move to passed pos.
	//SEE: setSelectedEntitiesGoal(...)
	void rightClickDown(Point<float> pos);

	//Call when the left mouse button is released UP.
	void rightClickUp(Point<float> pos);

	//Call when the middle mouse button is clicked DOWN.
	//For the time that this function was called and function: middleClickUp(...) is called,
	//	the camera will move with the mouse.
	void middleClickDown(Point<float> pos);

	//Call when the left mouse button is released UP.
	//SEE: middleMouseClickUp
	void middleClickUp(Point<float> pos);

	//Updates the GameWorld and all Entities.
	void update();

	//Draws the GameWorld and all Entities.
	void draw();

	~GameWorld();
};

#endif